還記得上一篇文章我們使用 port-forward
實現將本地的接口轉發到 Kubernetes 中指定的 Pod 操作嗎?而 Service
元件就是 Kubernetes 特地為了用來定義『一群 Pod 要如何被連線及存取』 的元件,此舉不只將暴露端口的任務解耦抽象出來,更利用 Labels
和 Seletor
來識別需要套用該設定這些屬於非永久資源的 Pod
,如此一來,當 Pod
被動態的創建或銷毀時,相較於直接使用 port-forward
的 Pod 將會失去他的暴露端口,而新創建出來的 Pod 會因為具有原來的 Labels
而繼續套用我們先前暴露端口的相關設定。
Service
是 Kubernetes
內定義的抽象化物件(object),官方網站的介紹傳神地描述它的基本(原始)用途。
A Kubernetes Service is an abstraction which defines a logical set of Pods and a policy by which to access them. Kubernetes Service 是個抽象化的概念,主要定義了邏輯上的一群 Pod 以及如何存取他們的規則。
簡單一句話描述就是帶著相同標籤、做類似事情的一群 Pod
。
每個 Pod 本身會帶著一或多個不等的標籤在身上,當 Service
指定存取某些特定的標籤時,Label Selector
會根據 Pod 身上自帶的標籤進行分組,並回傳 Service
所要求的 Pod 資訊。
Service
作為中介層,避免使用者和 Pod 進行直接連線,除了讓我們服務維持一定彈性能夠選擇不同的 Pod 來處理請求外,某種程度上亦避免裸露無謂的 Port 而導致資安問題。
另外,也體現出雲服務架構設計中一個非常重要的觀念:
對於使用者而言,僅須知道有人會處理他們的請求,而毋須知道實際上處理的人是誰。
就讓我們來由把昨天 foo
再新增一個夥伴 bar
,並且使用 Service 來實作看看如何管理這兩個 Pod
吧:
// pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: foo
labels:
app: foo
type: demo
spec:
containers:
- name: foo
image: mikehsu0618/foo
ports:
- containerPort: 8080
---
apiVersion: v1
kind: Pod
metadata:
name: bar
labels:
app: bar
type: demo
spec:
containers:
- name: bar
image: mikehsu0618/bar
ports:
- containerPort: 8080
撰寫 Service
設定 :
// service.yaml
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
selector:
type: demo
type: LoadBalancer
ports:
- protocol: TCP
port: 8000
targetPort: 8080
apiVersion
: Service 使用的Kubernetes API v1
版本metadata.name
: 該 Service 的名稱。spec.type
: 可以指定 Service 的型別,可以是NodePort
或是LoadBalancer
spec.ports.port
: 可以指定,創建的 Service 的 Cluster IP,是哪個 port number 去對應到targetPort
。spec.ports.nodePort
: 可以指定Node物件
是哪一個 port number,去對應到targetPort
,若是在 Service 的設定檔中沒有指定的話,Kubernetes 會隨機幫我們選一個 port number。spec.ports.targetPort
: targetPort 是我們指定的 Pod 的 port number,由於我們會在Pod中運行一個port number 8080 的 container (foo & bar),所以我們指定hello-service
的特定port number 都可以導到該 container。spec.ports.protocol
: 目前 Service 支援TCP
、 SCTP
與UDP
三種 protocol,預設為TCP
。spec.selector
: selector 則會幫我們過濾,在範例中,我們創建的 Service 會將特定的 port number 收到的流量導向 Lable 為 type=demo
的 Pods。運行一下設定檔:
kubectl apply -f pod.yaml,service.yaml
查看服務狀態:
kubectl get services // 查看服務
or
kubectl get all // 查看全部元件狀態
由上圖可以看出我們順利的 run 起一個 LoadBalancer
,如果我們的Kubernetes Cluster是架在第三方雲端服務(cloud provider),例如 Amazon 或 Google Cloud Platform,我們可以透過這些 cloud provider 提供的 LoadBalancer ,幫我們分配流量到每個 Node ,而我們使用 docker-desktop
直接會預設幫我們把 External IP
指向到我們的 [localhost](http://localhost)
。
由此一來,當我們使用 curl
去 call 我的設定好的 8000端口
,Kubernetes Service 就會將我們的流量隨機分配到 foo
bar
這兩個 container 中。
curl localhost:8000
Kubernetes
的Service
讓我們非常簡單的實現管理 Pod
流量以及 LoadBalance
的功能,在以前可是需要到雲端平台一個一個設定才可以辦到,Kubernetes
幫我們省下許多細節使我們可以專注在實現維運部署的邏輯上面,但背後的觀念非常值得我們回來細細咀嚼,在這裡只是先做一個簡單的小 demo,日後將會對 Service
的運作機制做更深入的了解。
千呼萬喚始出來!鐵人賽系列「從異世界歸來發現只剩自己不會 Kubernetes」同名改編作品出版了!
感謝所有交流指教的各路英雄,也感謝願意點閱文章的各位,如果能幫助到任何人都將會是我的榮幸。
本書內容改編自第 14 屆 iThome 鐵人賽 DevOps 組的優選系列文章《從異世界歸來發現只剩自己不會 Kubernetes》。此書是一本綜合性的指南,針對想要探索認識 Kubernetes 的技術人員而生。無論是初涉此領域的新手,還是已有深厚經驗的資深工程師,本書都能提供你所需的知識和技能。
「這本書不僅提供了豐富的範例程式碼和操作指南,讓身為工程師的我們能實際操作來加深認知;更重要的是,它教會我如何從後端工程師的角度去思考和應用 Kubernetes。從容器的生命週期、資源管理到部署管理,每一章都與我們的日常開發工作息息相關。」
──── 雷N │ 後端工程師 / iThome 鐵人賽戰友
天瓏連結: 從異世界歸來發現只剩自己不會 Kubernetes:初心者進入雲端世界的實戰攻略!
相關文章:
Reference
Kubernetes Service 深度剖析 - 標籤對於 Service 的影響
如果簡單加入解釋spec.type 的loadBalancer 會比較好。(加入幾個字,因為未必人人都熟識networking)
非常認同!但 Networking 很難幾個字解釋出來,我會再努力~
最後部份"curl localhost:8080" 後面的圖是顯示curl http://localhost:8000/ 結果.
已更正為 curl localhost:8000 呼叫 kubernetes service 的端口無誤
感謝~